package com.cai310.lottery.entity.lottery.jczq;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Type;
import org.hibernate.type.EnumType;

import com.cai310.lottery.cache.CacheConstant;
import com.cai310.lottery.common.Lottery;
import com.cai310.lottery.entity.lottery.Scheme;
import com.cai310.lottery.exception.DataException;
import com.cai310.lottery.support.Item;
import com.cai310.lottery.support.jczq.JczqCompoundContent;
import com.cai310.lottery.support.jczq.JczqMatchItem;
import com.cai310.lottery.support.jczq.JczqUtil;
import com.cai310.lottery.support.jczq.PassMode;
import com.cai310.lottery.support.jczq.PassType;
import com.cai310.lottery.support.jczq.PlayType;
import com.cai310.lottery.support.jczq.SchemeType;
import com.cai310.lottery.support.jczq.TicketItem;
import com.cai310.lottery.ticket.protocol.response.dto.JcMatchOdds;
import com.cai310.lottery.ticket.protocol.response.dto.JcMatchOddsList;
import com.cai310.lottery.ticket.protocol.response.dto.JcTicketOddsList;
import com.cai310.utils.JsonUtil;

/**
 * 竞彩足球方案实体类.
 * 
 */
@Entity
@Table(name = JczqScheme.TABLE_NAME)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = CacheConstant.H_SCHEME_CACHE_REGION)
public class JczqScheme extends Scheme {
    
    public static final String TABLE_NAME = com.cai310.lottery.Constant.LOTTERY_TABLE_PREFIX + "JCZQ_SCHEME";
    private static final long serialVersionUID = 2430623685086244555L;

    /** 过关方式 */
    private long passType;

    /** 
     * 玩法类型
     * 
     * @see com.cai310.lottery.support.dczc.PlayType
     */
    private PlayType playType;

    /**
     * 过关模式
     * 
     * @see com.cai310.lottery.support.dczc.PassMode
     * */
    private PassMode passMode;

    /**
     * 方案类型
     * 
     * @see com.cai310.lottery.support.jczq.SchemeType
     */
    private SchemeType schemeType;

    /** 出票的奖金值 */
    private String printAwards;

    /** 拆票后的内容 */
    private String ticketContent;

    /** 是否已真实出票 */
    private boolean realPrinted;

    /** 真实出票时间 */
    private Date realPrintTime;
    
    /** 撤单时间 */
    private Date cancelTime;
    /**
     * @return {@link #playType}
     */
    @Type(type = "org.hibernate.type.EnumType", parameters = {
            @Parameter(name = EnumType.ENUM, value = "com.cai310.lottery.support.jczq.PlayType"),
            @Parameter(name = EnumType.TYPE, value = PlayType.SQL_TYPE) })
    @Column(nullable = false, updatable = false)
    public PlayType getPlayType() {
        return playType;
    }

    /**
     * @param playType
     *            the {@link #playType} to set
     */
    public void setPlayType(PlayType playType) {
        this.playType = playType;
    }

    /**
     * @return {@link #passType}
     */
    @Column(nullable = false, updatable = false)
    public long getPassType() {
        return passType;
    }

    /**
     * @param passType
     *            the {@link #passType} to set
     */
    public void setPassType(long passType) {
        this.passType = passType;
    }

    /**
     * @return {@link #passMode}
     */
    @Type(type = "org.hibernate.type.EnumType", parameters = {
            @Parameter(name = EnumType.ENUM, value = "com.cai310.lottery.support.jczq.PassMode"),
            @Parameter(name = EnumType.TYPE, value = PassMode.SQL_TYPE) })
    @Column(nullable = false, updatable = false)
    public PassMode getPassMode() {
        return passMode;
    }

    /**
     * @param passMode
     *            the {@link #passMode} to set
     */
    public void setPassMode(PassMode passMode) {
        this.passMode = passMode;
    }

    /**
     * @return the schemeType
     */
    @Type(type = "org.hibernate.type.EnumType", parameters = {
            @Parameter(name = EnumType.ENUM, value = "com.cai310.lottery.support.jczq.SchemeType"),
            @Parameter(name = EnumType.TYPE, value = SchemeType.SQL_TYPE) })
    @Column(nullable = false, updatable = false)
    public SchemeType getSchemeType() {
        return schemeType;
    }

    /**
     * @param schemeType
     *            the schemeType to set
     */
    public void setSchemeType(SchemeType schemeType) {
        this.schemeType = schemeType;
    }
    /**
     * @return the {@link #printAwards}
     */
    @Lob
    @Column
    public String getPrintAwards() {
        return printAwards;
    }

    /**
     * @param printAwards
     *            the {@link #printAwards} to set
     */
    public void setPrintAwards(String printAwards) {
        this.printAwards = printAwards;
    }
    @Lob
    @Column
    public String getTicketContent() {
        return ticketContent;
    }

    public void setTicketContent(String ticketContent) {
        this.ticketContent = ticketContent;
    }
    /**
     * @return the {@link #realPrinted}
     */
    @Column(nullable = false)
    public boolean isRealPrinted() {
        return realPrinted;
    }

    /**
     * @param realPrinted
     *            the {@link #realPrinted} to set
     */
    public void setRealPrinted(boolean realPrinted) {
        this.realPrinted = realPrinted;
    }

    /**
     * @return the {@link #realPrintTime}
     */
    @Temporal(TemporalType.TIMESTAMP)
    @Column
    public Date getRealPrintTime() {
        return realPrintTime;
    }

    /**
     * @param realPrintTime
     *            the {@link #realPrintTime} to set
     */
    public void setRealPrintTime(Date realPrintTime) {
        this.realPrintTime = realPrintTime;
    }
    
    @Temporal(TemporalType.TIMESTAMP)
    @Column
    public Date getCancelTime() {
        return cancelTime;
    }

    public void setCancelTime(Date cancelTime) {
        this.cancelTime = cancelTime;
    }
    @Transient
    @Override
    public Lottery getLotteryType() {
        return Lottery.JCZQ;
    }
    /**
     * @return 获取选择的场次序号集合
     */
    @Transient
    public List<String> getSelectedMatchKeys() {
        switch (this.getMode()) {
        case COMPOUND:
            JczqCompoundContent compoundContent = getCompoundContent();
            List<String> matchKeys = new ArrayList<String>();
            for (JczqMatchItem item : compoundContent.getItems()) {
                matchKeys.add(item.getMatchKey());
            }
            return matchKeys;
        default:
            throw new RuntimeException("投注方式不合法");
        }
    }
    @Transient
    @Override
    public String getContentText() {
        Item[] allItem = getPlayType().getAllItems();

        final String seq = "\r\n";
        final char seq2 = ',';

        StringBuilder sb = new StringBuilder();

        sb.append("玩法类型：").append(getPlayType().getText()).append(seq);
        sb.append("过关模式：").append(getPassMode().getText()).append(seq);

        List<PassType> passTypes = getPassTypeList();
        sb.append("过关方式：");
        for (PassType passType : passTypes) {
            sb.append(passType.getText()).append(seq2);
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(seq);

        if (isCompoundMode()) {
            JczqCompoundContent content = getCompoundContent();
            if ((content.getDanMinHit() != null && content.getDanMinHit() > 0)
                    || (content.getDanMaxHit() != null && content.getDanMaxHit() > 0)) {
                sb.append("模糊设胆：");
                if (content.getDanMinHit() != null && content.getDanMinHit() > 0)
                    sb.append("胆码至少中").append(content.getDanMinHit()).append("场").append(seq2);
                if (content.getDanMaxHit() != null && content.getDanMaxHit() > 0)
                    sb.append("胆码至多中").append(content.getDanMaxHit()).append("场").append(seq2);
                sb.deleteCharAt(sb.length() - 1);
                sb.append(seq);
            }
            for (JczqMatchItem matchItem : content.getItems()) {
                if (matchItem.isDan())
                    sb.append("[胆]-");
                sb.append("[").append(matchItem.getMatchKey()).append("]：");
                if(PlayType.MIX.equals(getPlayType()))allItem = matchItem.getPlayType().getAllItems();
                for (Item item : allItem) {
                    if ((matchItem.getValue() & (1 << item.ordinal())) > 0) {
                        sb.append(item.getText()).append(seq2);
                    }
                }
                sb.deleteCharAt(sb.length() - 1);
                sb.append(seq);
            }
        } else {
            return null;
        }
        return sb.toString();
    }

    @SuppressWarnings("unchecked")
    @Transient
    public JczqCompoundContent getCompoundContent() {
        if (StringUtils.isBlank(this.getContent()))
            return null;

        @SuppressWarnings("rawtypes")
        Map classMap = new HashMap();
        classMap.put("items", JczqMatchItem.class);
        return JsonUtil.getObject4JsonString(this.getContent(), JczqCompoundContent.class, classMap);
    }

    @Transient
    public List<PassType> getPassTypeList() {
        return PassType.getPassTypes(this.getPassType());
    }

    @Transient
    public String getPassTypeText() {
        return PassType.getPassTypeText(this.getPassType());
    }

    @Transient
    public List<TicketItem> getTicketList() throws DataException {
        List<TicketItem> list = new ArrayList<TicketItem>();
        String[] arr = this.getTicketContent().trim().split(TicketItem.ITEM_AND);
        for (String content : arr) {
            list.add(TicketItem.valueOf(content));
        }
        return list;
    }

    @Transient
    public int getTicketNum() {
        if (StringUtils.isBlank(this.getTicketContent()))
            return 1;

        return this.getTicketContent().trim().split(TicketItem.ITEM_AND).length;
    }

    @Transient
    public List<Map<String, Map<String, Double>>> getPrintAwardList() throws DataException {
        if (passMode == PassMode.SINGLE){
            if(!PlayType.BF.equals(this.getPlayType())){
                return null;
            }
        }
        if(StringUtils.isBlank(this.getPrintAwards()))return null;

        int ticketNum = getTicketNum();
        if (ticketNum == 0)ticketNum = 1; 
        List<Map<String, Map<String, Double>>> list = new ArrayList<Map<String, Map<String, Double>>>(ticketNum);
        for (int i = 0; i < ticketNum; i++) {
            list.add(null);
        }
        String awardString = this.getPrintAwards();
        @SuppressWarnings("rawtypes")
        Map classMap = new HashMap();
        classMap.put("awardList", JcMatchOddsList.class);
        classMap.put("jcMatchOdds", JcMatchOdds.class);
        JcTicketOddsList jcTicketOddsList = JsonUtil.getObject4JsonString(awardString, JcTicketOddsList.class, classMap);
        List<JcMatchOddsList> jcMatchOdds = jcTicketOddsList.getAwardList();
        
        for (int i = 0; i < jcMatchOdds.size(); i++) {
            JcMatchOddsList jcMatchOddsList = jcMatchOdds.get(i);
            Integer ticketIndex=jcMatchOddsList.getTicketIndex();
            if (ticketIndex>= list.size())
                throw new DataException("出票SP值数据异常.");
            Map<String, Map<String, Double>> map = JczqUtil.getPrintAwardMap(jcMatchOddsList.getJcMatchOdds());
            list.set(ticketIndex, map);
        }
        return list;
    }

    public void addPrintAward(String printAward) {
        if (passMode == PassMode.SINGLE)
            return;

        JSONArray jsonArr;
        if (StringUtils.isBlank(this.getPrintAwards())) {
            jsonArr = JSONArray.fromObject("[]");
        } else {
            jsonArr = JSONArray.fromObject(this.getPrintAwards());
        }
        jsonArr.add(printAward);

        this.setPrintAwards(jsonArr.toString());
    }

    public void addPrintAward(JSONObject printAward) {
        if (passMode == PassMode.SINGLE)
            return;

        JSONArray jsonArr;
        if (StringUtils.isBlank(this.getPrintAwards())) {
            jsonArr = JSONArray.fromObject("[]");
        } else {
            jsonArr = JSONArray.fromObject(this.getPrintAwards());
        }
        jsonArr.add(printAward);

        this.setPrintAwards(jsonArr.toString());
    }
    @Transient
    @Override
    public Byte getPlayTypeOrdinal() {
        return (byte) getPlayType().ordinal();
    }
}
